package com.lagou.client;

import com.lagou.boot.ConsumerBoot;
import com.lagou.configBean.ZkClient;
import com.lagou.handler.UserClientHandler;
import com.lagou.protocol.JSONSerializer;
import com.lagou.protocol.RpcDecoder;
import com.lagou.protocol.RpcEncoder;
import com.lagou.protocol.RpcRequest;
import com.lagou.rpc.DiscoverService;
import com.lagou.rpc.FastFindLink;
import com.lagou.rpc.RandomFindLink;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import org.apache.curator.framework.CuratorFramework;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 消费者
 */
public class RPCConsumer {

    //1.创建一个线程池对象  -- 它要处理我们自定义事件
    private static ExecutorService executorService =
            Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());





    //4.编写一个方法,使用JDK的动态代理创建对象
    // serviceClass 接口类型,根据哪个接口生成子类代理对象;   providerParam :  "UserService#sayHello#"
    public static Object createProxy(Class<?> serviceClass){
        return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
                new Class[]{serviceClass}, new InvocationHandler() {
                    public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
                        //1)初始化客户端cliet
//                        if(userClientHandler == null){
//                            initClient();
//                        }
                        //TODO 之后通过反射  设置rpcReuest 的参数值

                        RpcRequest rpcRequest = new RpcRequest();

                        String className = method.getDeclaringClass().getName();
                        String methodName = method.getName();

                        Class<?>[] parameterTypes = method.getParameterTypes();

                        rpcRequest.setRequestId(UUID.randomUUID().toString());
                        rpcRequest.setClassName(className);
                        rpcRequest.setMethodName(methodName);
                        rpcRequest.setParameterTypes(parameterTypes);
                        rpcRequest.setParameters(objects);


                        DiscoverService.setFindLinkHandler(new FastFindLink());
                        String serviceIp = DiscoverService.userClientHandlerFromMap();
                        if(null == serviceIp){
                            System.out.println("没找最快响应服务器,调用服务器随机方法");
                            DiscoverService.setFindLinkHandler(new RandomFindLink());
                        }
                        serviceIp = DiscoverService.userClientHandlerFromMap();

                        UserClientHandler userClientHandler = DiscoverService.getTcpLink().get(serviceIp);

                        //2)给UserClientHandler 设置param参数
                        userClientHandler.setParam(rpcRequest);

                        Long startTime =  System.currentTimeMillis();
                        //3).使用线程池,开启一个线程处理处理call() 写操作,并返回结果
                        Object result = executorService.submit(userClientHandler).get();

                        CuratorFramework client = ZkClient.getZKClient();
                        client.setData().forPath(ConsumerBoot.serverName+serviceIp,
                                Long.valueOf(System.currentTimeMillis()-startTime).toString().getBytes());

                        //4)return 结果
                        return result;
                    }
                });
    }

}
